library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity ITMAN is
	Port ( intsgn : out STD_LOGIC;
		intsgnstr : out STD_LOGIC;
		intsgnack : in STD_LOGIC;
		v1 : in STD_LOGIC_VECTOR (15 downto 0);
		v1in : in STD_LOGIC;
		v1ack : out STD_LOGIC;
		v2 : in STD_LOGIC_VECTOR (15 downto 0);
		v2in : in STD_LOGIC;
		v2ack : out STD_LOGIC;
		a : out STD_LOGIC_VECTOR (15 downto 0);
		astr : out STD_LOGIC;
		aack : in STD_LOGIC;
		b : out STD_LOGIC_VECTOR (15 downto 0);
		bstr : out STD_LOGIC;
		back : in STD_LOGIC;
		clkin : in STD_LOGIC);
end ITMAN;

architecture Behavioral of ITMAN is
	type estados is(inicio, fst_iter, wait_v2, nth_iter);
	begin
	dados: process(clkin, intsgnack, v1in, v2in, aack, back)
		variable estado: estados := inicio;
		APÊNDICE A. IMPLEMENTAÇÃO DE GRAFOS A FLUXO DE DADOS 109
		variable v1d: STD_LOGIC_VECTOR (15 downto 0);
		variable v2d: STD_LOGIC_VECTOR (15 downto 0);
		variable envinitsgn: STD_LOGIC := '0';
		variable enva: STD_LOGIC := '0';
		variable envb: STD_LOGIC := '0';
	begin
		if clkin'event and clkin = '1' then
			intsgn <= '0';
			intsgnstr <= '0';
			v1ack <= '0';
			v2ack <= '0';
			a <= "ZZZZZZZZZZZZZZZZ";
			astr <= '0';
			b <= "ZZZZZZZZZZZZZZZZ";
			bstr <= '0';
			case estado is
				when inicio =>
					v2d := "0000000000000000"; -- um valor qualquer para v2
					if v1in = '1' then
						v1d := v1;
						v1ack <= '1';
						estado := fst_iter;
					end if;
				when fst_iter =>
					if intsgnack = '1' then
						envinitsgn := '1';
					end if;
					if envinitsgn = '0' then
						intsgn <= '0';
						intsgnstr <= '1';
					end if;
					if aack = '1' then
						enva := '1';
					end if;
					if enva = '0' then
						a <= v1d;
						astr <= '1';
					end if;
					if back = '1' then
						envb := '1';
					end if;
					if envb = '0' then
						b <= v2d;
						bstr <= '1';
					end if;
					if envinitsgn = '1' and enva = '1' and envb = '1' then
						envinitsgn := '0';
						enva := '0';
						envb := '0';
						estado := wait_v2;
					end if;
				when nth_iter =>
					if aack = '1' then
						enva := '1';
					end if;
					if enva = '0' then
						a <= v1d;
						astr <= '1';
					end if;
					if back = '1' then
						envb := '1';
					end if;
					if envb = '0' then
						b <= v2d;
						bstr <= '1';
					end if;
					if enva = '1' and envb = '1' then
						enva := '0';
						envb := '0';
						estado := wait_v2;
					end if;
				when wait_v2 =>
					if v2in = '1' then
						v2d := v2;
						v2ack <= '1';
						estado := nth_iter;
					end if;
			end case;
		end if;
	end process dados;
end Behavioral;